package com.geekhalo.demo.enums.code.fix;

import com.geekhalo.lego.common.enums.CodeBasedEnum;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter;
import org.springframework.stereotype.Component;


import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Component
public class CodeBasedEnumConverter implements ConditionalGenericConverter {
    private final List<Class> enumsCls = Lists.newArrayList();

    public CodeBasedEnumConverter() {
        // 注册转换类型 CodeBasedOrderStatus
        this.enumsCls.add(CodeBasedOrderStatus.class);
    }
    /**
     * 匹配实现 CodeBasedEnum 的枚举
     * @param sourceType
     * @param targetType
     * @return
     */
    @Override
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        Class<?> type = targetType.getType();
        return this.enumsCls.stream()
                .anyMatch(t -> t == type);
    }

    /**
     * 匹配<String,枚举类型>
     * @return
     */
    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        return this.enumsCls.stream()
                .map(t -> new ConvertiblePair(String.class, t))
                .collect(Collectors.toSet());

    }

    /**
     * 完成枚举转化
     * @param source
     * @param sourceType
     * @param targetType
     * @return
     */
    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        String value = (String) source;
        // 空值处理
        if (StringUtils.isEmpty(value)) {
            return null;
        }

        Class targetCls = targetType.getType();
        // 匹配失败
        if (!this.enumsCls.contains(targetCls)){
            return null;
        }

        // 遍历枚举所有 Value
        for (Object enumValue : targetCls.getEnumConstants()){
            // 判断枚举的 code
            String code = String.valueOf(((CodeBasedEnum) enumValue).getCode());
            if(value.equals(code)) {
                return enumValue;
            }
            // 判断枚举 Name
            String name = ((Enum) enumValue).name();
            if (value.equals(name)){
                return enumValue;
            }
        }
        return null;
    }
}
